package com.easychat.aspect;

import com.easychat.annotation.GlobalInterceptor;
import com.easychat.entity.constants.RedisConstants;
import com.easychat.entity.dto.TokenUserInfoDto;
import com.easychat.entity.enums.ResponseCodeEnum;
import com.easychat.exception.BusinessException;
import com.easychat.redis.RedisCache;
import com.easychat.utils.StringTools;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Author Dongdong
 * @注释 全局操作切面
 */

@Aspect
@Component
public class GlobalOperationAspect {
    //redis
    @Resource
    private RedisCache redis;
    //日志工具
    private Logger logger = LoggerFactory.getLogger(GlobalOperationAspect.class);

    // 定义切点
    @Pointcut("@annotation(com.easychat.annotation.GlobalInterceptor)")
    private void pointcut() {}

    @Before(value = "pointcut()")
    public void interceptor(JoinPoint joinPoint) {

        try {
            // 获取注解中定义的方法
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            // 获取注解
            GlobalInterceptor annotation = method.getAnnotation(GlobalInterceptor.class);
            // 判断注解是否存在
            if (annotation == null) {
                return;
            }
            // 判断加了注解的地方，使用了哪些参数 ex：@GlobalInterceptor(checkLogin = true)
            if (annotation.checkLogin() || annotation.checkAdmin()) {
                checkLogin(annotation.checkAdmin());
            }
        } catch (BusinessException e) {
            logger.error("全局拦截异常", e);
            throw e;
        } catch (Exception e) {
            logger.error("全局拦截异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            logger.error("全局拦截异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }

    public void checkLogin(Boolean checkAdmin) {
        // 获取请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String token = request.getHeader("token");
        if (StringTools.isEmpty(token)) {
            throw new BusinessException(ResponseCodeEnum.CODE_901);
        }
        // 获取token请求体信息
        TokenUserInfoDto tokenUserInfoDto = (TokenUserInfoDto) redis.getCacheObject(RedisConstants.REDIS_KEY_WS_TOKEN + token);
        // token请求体为空说明 未登录
        if (tokenUserInfoDto == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_901);
        }

        //非管理员用户请求管理端接口
        // 该接口需要检验是否是管理员&&
        if (checkAdmin && !tokenUserInfoDto.getAdmin()) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }
    }

}

